 #
	# Table of Contents Generator
	# Developer: Ryan Smith
	# Copyright 2008 Ryan Smith
		
	# This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.

    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.

    # You should have received a copy of the GNU General Public License
    # along with this program.  If not, see <http://www.gnu.org/licenses/>.

import wx
import time
import os
from wx.lib.wordwrap import wordwrap
import wx.lib.hyperlink as hl
# import psyco
# psyco.profile()

# Defined ID values
ID_SAVE =  100
ID_TIME =  101
ID_EXIT =  102
ID_ABOUT = 103

def custom_listdir(path):
	"""	Returns the content of a directory by showing directories first	and then files by ordering the names alphabetically	"""
	# http://zeta-puppis.com/2008/02/15/python-listdir-order/
	dirs = sorted([d for d in os.listdir(path) if os.path.isdir(path + os.path.sep + d)])
	dirs.extend(sorted([f for f in os.listdir(path) if os.path.isfile(path + os.path.sep + f)]))
	return dirs

class MainWindow(wx.Frame):
	def __init__(self, parent, id, title):
		wx.Frame.__init__(self, parent, wx.ID_ANY, title, size = (600,600), style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
		
		# Make some panels for the frame to put things in
		panel1 = wx.Panel(self, -1) # tree
		panel2 = wx.Panel(self, -1) # text
		panel3 = wx.Panel(self, -1) # buttons
		
		self.dirname = ''
		self.filename = ''
		self.FileOpen = 0
		
		# Put the things into the panels
		self.dirtree = wx.GenericDirCtrl(panel1, wx.ID_ANY, style = wx.DIRCTRL_DIR_ONLY)
		self.control = wx.TextCtrl(panel2, wx.ID_ANY, style = wx.TE_MULTILINE)
		self.statusbar = self.CreateStatusBar()
		
		# Save button and binding
		bSave = wx.Button(panel3, ID_SAVE, "Save")
		self.Bind(wx.EVT_BUTTON, self.OnSave, bSave)
		# Timestamp button and binding
		bTime = wx.Button(panel3, ID_TIME, "Timestamp")
		self.Bind(wx.EVT_BUTTON, self.OnTimestamp, bTime)
		# Exit button and binding
		bExit = wx.Button(panel3, ID_EXIT, "Exit")
		self.Bind(wx.EVT_BUTTON, self.OnExit, bExit)
		# About Dialog
		bAbout = wx.Button(panel3, ID_ABOUT, "About")
		self.Bind(wx.EVT_BUTTON, self.OnAbout, bAbout)

		# The buttons should have a sizer to make them nice and neat
		buttonBox = wx.BoxSizer(wx.VERTICAL)
		buttonBox.Add(bSave,  0, wx.ALL | wx.EXPAND, border = 2) # 5
		buttonBox.Add(bTime,  0, wx.ALL | wx.EXPAND, border = 2) #6		
		buttonBox.Add(bAbout, 0, wx.ALL | wx.EXPAND, border = 2) #5
		buttonBox.Add(bExit,  0, wx.ALL | wx.EXPAND, border = 2) #5
		
		# 3 vertical sizers one for each panel, and one container horizontal box	
		hbox = wx.BoxSizer(wx.HORIZONTAL)
		vbox1 = wx.BoxSizer(wx.VERTICAL)
		vbox2 = wx.BoxSizer(wx.VERTICAL)
		vbox3 = wx.BoxSizer(wx.VERTICAL)
		# size the 'things' in their respective panels
		vbox1.Add(self.dirtree, 1, wx.EXPAND)
		vbox2.Add(self.control, 1, wx.EXPAND)
		vbox3.Add(buttonBox, 1, wx.EXPAND)
		# put the panels in the container
		hbox.Add(panel1, 2, wx.EXPAND)
		hbox.Add(panel2, 3, wx.EXPAND)
		hbox.Add(panel3, 1, wx.EXPAND)
		#size the panels
		panel1.SetSizer(vbox1)
		panel2.SetSizer(vbox2)
		panel3.SetSizer(vbox3)
		# put it all together
		self.SetSizer(hbox) # from panel

		# the GenericDirCtrl doesn't have info of its own ... it is a widget around a widget so we need to get the event from the tree control
		self.tree = self.dirtree.GetTreeCtrl()
		self.Bind(wx.EVT_TREE_SEL_CHANGED, self.CreateToC, id = self.tree.GetId()) # Bind the event to each time the directory is changed, create a toc and put it in the right panel ... the id I believe is to help with the treeCtrl bit
		
		#self.CreateToC(0) #run a default case to generate something from the start
		self.Show(True)

	def OnAbout(self, event):
		""" About information """
		
		#gnuLink = hl.HyperLinkCtrl(self, wx.ID_ANY, "<http://www.gnu.org/licenses/>.\n", URL = "http://www.gnu.org/licenses/")
		licenseText = "\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>."
		
		info = wx.AboutDialogInfo()
		info.SetName("Table of Contents Generator")
		info.SetVersion("0.6")
		info.SetCopyright("Copyright 2008 Ryan Smith")
		info.SetDescription(wordwrap("\nThis program makes generating an alphanumerically sorted folder and file listing of a chosen directory easy. It also aids in giving a written description about each folder or file if desired.\n", 350, wx.ClientDC(self)))
		#info.WebSite = ("http://en.wikipedia.org/wiki/Hello_world", "Hello World home page")
		info.AddDeveloper("Ryan Smith")
		info.SetLicense(wordwrap(licenseText, 350, wx.ClientDC(self)))

		# Then we call wx.AboutBox giving it that info object
		wx.AboutBox(info)
		
	def OnTimestamp(self, event):
		""" Inserts a time stamp into the document """
		t = time.localtime(time.time())
		self.control.WriteText(time.strftime("%I:%M %p %d %b %Y\n", t))
		
	def OnExit(self, event): # exit the program
		""" Kill the program """
		self.Close(True)
		
	def OnSave(self, event): # Save a file 
		""" Save the file to the original file location .... otherwise use saveas """
		if self.FileOpen == 1:
			f = open(os.path.join(self.dirname, self.filename), "w")
			f.write(self.control.GetValue())
			self.SetStatusText("Saved: " +self.dirname+"\\"+self.filename)
			f.close()
		else:
			self.OnSaveAs(event)
	
	def OnSaveAs(self, event): # Save file to a new path
		""" Save to an arbitrary file and path """
		dlg = wx.FileDialog(self, "Save As", self.dirname, self.filename, "Text Files (*.txt)|*.txt|All Files|*.*", wx.SAVE)
		if (dlg.ShowModal() == wx.ID_OK):
			self.filename = dlg.GetFilename()
			self.dirname = dlg.GetDirectory()
			self.FileOpen = 1
			self.OnSave(event)
		dlg.Destroy()

	def CreateToC(self, event):
		""" Creates a table of contents of the given selected directory """
		dname = self.dirtree.GetPath()
		dname = str(dname) # custom_listdir needs a str to operate on ...
		x = custom_listdir(dname) # generates a sorted listing of the directory, alphanumeric with folders first then files
		#  y is the header information for the buffer
		y = '### Generated on: ' + str(time.strftime("%a %d %b %Y %H:%M:%S ", time.strptime(time.ctime())))
		y += '\n### Current Directory: ' + str(dname)
		y += '\n### Contains ' + str(len(x)) + ' files'
		y += '\n### [_]- Indicates a folder'
		y += '\n### **-  Indicates a file  \n\n'
		
		# This checks to see if a path is a folder of file and assigns an appropriate ascii identifier
		for x in x:
			if os.path.isdir((os.path.join(dname, x))):
				y += '\n[_]- ' + str(x) + '\n\t- '
			elif os.path.isfile((os.path.join(dname, x))):
				y += '\n**- ' + str(x) + '\n\t- '
			else:
				y += '\n##- ' + str(x) + '\n\t- '

		self.control.SetValue(y)

app = wx.App(0)
frame = MainWindow(None, -1, "Table of Contents Generator")
app.MainLoop()